const std = @import("std");
const uart = @import("uart.zig");
pub const print = uart.print;

const page = @import("page.zig");
const allocator = page.fba.allocator();

const STACK_SIZE = 1024 * 16;
export var stack0: [STACK_SIZE]u8 align(16) = undefined;

const start_code = std.fmt.comptimePrint(
    \\  csrr    t0, mhartid
    \\  beqz    t0, hart_0
    \\
    \\park:
    \\  wfi
    \\  j       park
    \\
    \\hart_0:
    \\  # Setup stacks, the stack grows from bottom to top, so we put the
    \\  # stack pointer to the very end of the stack range.
    \\  la      sp, stack0 + {}     # set the initial stack pointer
    \\                              # to the end of the first stack space
    \\  j       start               # hart 0 jump to start function
, .{STACK_SIZE});

export fn _start() linksection(".os_start") callconv(.naked) noreturn {
    asm volatile (start_code);
}

export fn start() noreturn {
    uart.init();
    page.init();
    main() catch |e| @panic(@errorName(e));

    print("-------------- end.. ---------------\n", .{});
    while (true) {} // stop here!
}

const len = 12;

fn main() !void {
    print("Hello, RVOS!\n", .{});

    const buf: [len]u8 = @splat(65);
    print("buf[len - 1]: {c}\n", .{buf[len - 1]});

    // test
    const memory = try allocator.alloc(u8, 100);
    defer allocator.free(memory);

    memory[0] = 128;
    print("memory addr: {*}, memory[0]: {}\n", .{ memory, memory[0] });

    var x: u8 = 254;
    x += 1;
    print("got here\n", .{});
}

pub fn panic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
    @branchHint(.cold);
    print("KERNEL PANIC: {s}\n", .{msg});
    while (true) {}
}
